package top.infopub.job.fia.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.infopub.enums.fia.OrgSumTypesEnum;
import top.infopub.generic.GenericDao;
import top.infopub.generic.GenericServiceImpl;
import top.infopub.job.fia.dao.FundsPlanDao;
import top.infopub.job.fia.domain.FundsPlanSumDomain;
import top.infopub.job.fia.service.FundsPlanService;
import top.infopub.job.hr.dao.OrgInfoDao;
import top.infopub.model.fia.FundsPlan;
import top.infopub.model.fia.FundsPlanSummary;
import top.infopub.model.fia.FundsPlanTask;
import top.infopub.model.hr.OrgInfo;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FundsPlanServiceImpl extends GenericServiceImpl<FundsPlan, String> implements
        FundsPlanService {
    private static final Logger log = LoggerFactory.getLogger(FundsPlanServiceImpl.class);

	@Autowired
	private FundsPlanDao fundsPlanDao;

	@Autowired
    private OrgInfoDao orgInfoDao;
	
	@Override
	public GenericDao<FundsPlan, String> getDao() {
		return fundsPlanDao;
	}

    @Override
    @Transactional
    public void fundsPlanSummary() {
        List<FundsPlanTask> taskList = fundsPlanDao.queryFundsPlanTaskList("0");
        if (taskList != null && taskList.size() > 0) {
            log.info("月度资金计划待汇总数量：{}", taskList.size());
            for (FundsPlanTask task : taskList) {
                if (task == null) continue;
                //统计金额
                List<FundsPlanSumDomain> fpsdList = fundsPlanDao.queryFundsPlanSumById(task.getFundsPlanId());
                if (fpsdList == null || fpsdList.size() <= 0) continue;
                FundsPlanSumDomain fpsdNext = fundsPlanDao.querySumNextAmtById(task.getFundsPlanId());
                if (fpsdNext == null) fpsdNext = new FundsPlanSumDomain();
                if (fpsdNext.getSumNextAmt() == null) fpsdNext.setSumNextAmt(new BigDecimal(0));
                if (fpsdNext.getSumLowestAmt() == null) fpsdNext.setSumLowestAmt(new BigDecimal(0));
                Map<String, Object> map = new HashMap<>();
                BigDecimal sumAmt = new BigDecimal(0);
                for (FundsPlanSumDomain fpsd : fpsdList) {
                    if (fpsd == null) continue;
                    if (StringUtils.isBlank(fpsd.getCurrDate())) continue;
                    if (fpsd.getSumAmt() == null) fpsd.setSumAmt(new BigDecimal(0));
                    int d = Integer.valueOf(fpsd.getCurrDate().substring(fpsd.getCurrDate().lastIndexOf("-") + 1));
                    String key = "d" + d;
                    map.put(key, fpsd.getSumAmt());
                    sumAmt = sumAmt.add(fpsd.getSumAmt());
                }
                FundsPlanSumDomain fpsd = fpsdList.get(0);
                if (fpsd.getSumAmt() == null) fpsd.setSumAmt(new BigDecimal(0));
                //统计金额-所属公司
                OrgInfo thisOrg = orgInfoDao.selectByPrimaryKey(fpsd.getSgOrgId());
                if (thisOrg == null) continue;
                //查询上级公司-需要查询到TYPES=2或TYPES=1为止
                OrgInfo parentOrg = orgInfoDao.selectByPrimaryKey(thisOrg.getParentId());
                while (true) {
                    if (parentOrg == null) break;
                    if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES1.getCode(), parentOrg.getTypes())
                            || StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES2.getCode(), parentOrg.getTypes())) break;
                    parentOrg = orgInfoDao.selectByPrimaryKey(parentOrg.getParentId());
                }
                //汇总名称设置
                OrgSumTypesEnum oste = getOrgSumTypes(thisOrg, parentOrg);
                //设置默认名称
                String name = oste.getName();
                //如果得到的枚举类为1=总部，设置名称为公司名称
                if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES1.getCode(), oste.getCode())) {
                    name = thisOrg.getCompName();
                }
                //根据所属公司和归属年月查询汇总记录
                map.put("hrOrgId", fpsd.getSgOrgId());
                map.put("orgTypes", thisOrg.getTypes());
                map.put("orgSumTypes", oste.getCode());
                map.put("belongDate", fpsd.getBelongDate());
                map.put("sumAmt", sumAmt);
                map.put("uptBy", fpsd.getAddBy());
                map.put("uptTime", new Date());
                map.put("name", name);
                map.put("nextMonAmt", fpsdNext.getSumNextAmt());
                map.put("lowestMonAmt", fpsdNext.getSumLowestAmt());
                FundsPlanSummary tmpFps = fundsPlanDao.queryByOrgIdAndBelongDate(fpsd.getSgOrgId(), fpsd.getBelongDate());
                //原来累加到区域公司/总部的金额
                Map<String, BigDecimal> oldAmtMap = new HashMap<>();
                //项目公司或直属项目公司汇总自己当前的信息
                if (tmpFps == null) {
                    map.put("addBy", fpsd.getAddBy());
                    map.put("addTime", new Date());
                    fundsPlanDao.insertFundsPlanSummary(map);
                } else {
                    map.put("id", tmpFps.getId());
                    oldAmtMap = setAmtMap(tmpFps);
                    fundsPlanDao.updateFundsPlanSummary(map);
                }
                //找到汇总的项目公司/直属项目公司对应的区域公司或总部，进行金额累计
                while (parentOrg != null) {
                    //所属公司-TYPES为1或2
                    thisOrg = orgInfoDao.selectByPrimaryKey(parentOrg.getId());
                    //查询上级公司
                    parentOrg = orgInfoDao.selectByPrimaryKey(thisOrg.getParentId());
                    //汇总名称设置
                    oste = getOrgSumTypes(thisOrg, parentOrg);
                    //设置默认名称
                    name = oste.getName();
                    //如果得到的枚举类为1=总部，设置名称为公司名称
                    if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES1.getCode(), oste.getCode())) {
                        name = thisOrg.getCompName();
                    }
                    //根据所属公司和归属年月查询汇总记录
                    tmpFps = fundsPlanDao.queryByOrgIdAndBelongDate(thisOrg.getId(), fpsd.getBelongDate());
                    Map<String, Object> tmpMap = new HashMap<>();
                    tmpMap.putAll(map);
                    tmpMap.put("hrOrgId", thisOrg.getId());
                    tmpMap.put("orgTypes", thisOrg.getTypes());
                    tmpMap.put("orgSumTypes", oste.getCode());
                    tmpMap.put("belongDate", fpsd.getBelongDate());
                    tmpMap.put("sumAmt", sumAmt);
                    tmpMap.put("uptBy", fpsd.getAddBy());
                    tmpMap.put("uptTime", new Date());
                    tmpMap.put("name", name);
                    tmpMap.put("nextMonAmt", fpsdNext.getSumNextAmt());
                    tmpMap.put("lowestMonAmt", fpsdNext.getSumLowestAmt());
                    if (tmpFps == null) {
                        tmpMap.put("addBy", fpsd.getAddBy());
                        tmpMap.put("addTime", new Date());
                        fundsPlanDao.insertFundsPlanSummary(tmpMap);
                    } else {
                        //先把以前累计的金额扣除在把新的金额累计上去
                        BigDecimal tmpSumAmt = tmpFps.getSumAmt().subtract(oldAmtMap.get("sumAmt")).add(sumAmt);
                        tmpMap.put("sumAmt", tmpSumAmt);
                        BigDecimal tmpNext = tmpFps.getNextMonAmt().subtract(oldAmtMap.get("nextMonAmt")).add(fpsdNext.getSumNextAmt());
                        tmpMap.put("nextMonAmt", tmpNext);
                        BigDecimal tmpLowest = tmpFps.getLowestMonAmt().subtract(oldAmtMap.get("lowestMonAmt")).add(fpsdNext.getSumLowestAmt());
                        tmpMap.put("lowestMonAmt", tmpLowest);
                        tmpMap.put("id", tmpFps.getId());
                        Map<String, BigDecimal> thisAmtMap = setAmtMap(tmpFps);
                        for (int i = 1; i <= 31; i++) {
                            String key = "d" + i;
                            Object thisObj = map.get(key);
                            BigDecimal addAmt = new BigDecimal(0);
                            if (thisObj != null) addAmt = (BigDecimal) thisObj;
                            BigDecimal oldAmt = oldAmtMap.get(key);
                            BigDecimal tmpAmt = thisAmtMap.get(key).subtract(oldAmt).add(addAmt);
                            tmpMap.put(key, tmpAmt);
                        }
                        fundsPlanDao.updateFundsPlanSummary(tmpMap);
                    }
                }
                fundsPlanDao.updateFundsPlanTaskStatus("1", task.getId());
            }
        }
    }

    private OrgSumTypesEnum getOrgSumTypes(OrgInfo thisOrg, OrgInfo parentOrg) {
	    //上级公司不为空
        if (parentOrg != null) {
            //如果上级公司类型为1=总部
            if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES1.getCode(), parentOrg.getTypes())) {
                if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES1.getCode(), thisOrg.getTypes())) {
                    //如果当前公司类型为1=总部，
                    return OrgSumTypesEnum.ORG_SUM_TYPES1;
                } else if (StringUtils.equals(OrgSumTypesEnum.ORG_SUM_TYPES3.getCode(), thisOrg.getTypes())) {
                    //如果当前公司类型为3=项目公司，返回项目直属公司
                    return OrgSumTypesEnum.ORG_SUM_TYPES4;
                }
            }
            //如果上级公司是2=区域公司/3=项目公司，返回当前公司类型对应的枚举类
            return OrgSumTypesEnum.getByCode(thisOrg.getTypes());
        }
        //上级公司不存在，默认为最顶级的1=总部
        return OrgSumTypesEnum.ORG_SUM_TYPES1;
    }

    private Map<String, BigDecimal> setAmtMap(FundsPlanSummary fps) {
	    Map<String, BigDecimal> map = new HashMap<>();
	    if (fps == null) return map;
	    map.put("sumAmt", fps.getSumAmt());
        map.put("nextMonAmt", fps.getNextMonAmt());
        map.put("lowestMonAmt", fps.getLowestMonAmt());
        map.put("d1", fps.getD1());
        map.put("d2", fps.getD2());
        map.put("d3", fps.getD3());
        map.put("d4", fps.getD4());
        map.put("d5", fps.getD5());
        map.put("d6", fps.getD6());
        map.put("d7", fps.getD7());
        map.put("d8", fps.getD8());
        map.put("d9", fps.getD9());
        map.put("d10", fps.getD10());
        map.put("d11", fps.getD11());
        map.put("d12", fps.getD12());
        map.put("d13", fps.getD13());
        map.put("d14", fps.getD14());
        map.put("d15", fps.getD15());
        map.put("d16", fps.getD16());
        map.put("d17", fps.getD17());
        map.put("d18", fps.getD18());
        map.put("d19", fps.getD19());
        map.put("d20", fps.getD20());
        map.put("d21", fps.getD21());
        map.put("d22", fps.getD22());
        map.put("d23", fps.getD23());
        map.put("d24", fps.getD24());
        map.put("d25", fps.getD25());
        map.put("d26", fps.getD26());
        map.put("d27", fps.getD27());
        map.put("d28", fps.getD28());
        map.put("d29", fps.getD29());
        map.put("d30", fps.getD30());
        map.put("d31", fps.getD31());
	    return map;
    }
}